/**
 ****************************************************************************
 * Copyright (C) Marcelo F. Ochoa. All rights reserved.                      *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 */

package com.prism.toolkit;

import com.prism.toolkit.http.JxtpHttpServletRequest;

import com.prism.toolkit.http.JxtpHttpServletResponse;

import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;

import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;

import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Jowa {
    private static Logger log = null;

    public static Properties jowaProps = null;
    public static Hashtable cgiVars = null;
    public static HttpServletRequest req = null;
    public static HttpServletResponse res = null;
    public static int authScheme;
    public static String protectionRealm;
    public static String userId;
    public static String password;
    public static String ipAddress;
    public static String hostname;
    public static Hashtable parsedCookies;

    public Jowa() {
    }
    
    public static int INITIALIZE() throws SQLException {
        int majVersion = 2;
        int minVersion = 1;
        protectionRealm = "new DB Login";
        jowaProps = new Properties();
        // initialize log4j using log4j.properties file
        // solve caveats of log4j when loading properties file
        ResourceBundle rb = ResourceBundle.getBundle("log4j");
        Enumeration en = rb.getKeys();
        while(en.hasMoreElements()) {
            String key = (String)en.nextElement();
            String value = rb.getString(key);
            jowaProps.setProperty(key,value);
        }
        PropertyConfigurator.configure(jowaProps);
        log = Logger.getLogger(Jowa.class);
        // Initialize jowa resource bundle
        rb = ResourceBundle.getBundle("jowa");
        en = rb.getKeys();
        while(en.hasMoreElements()) {
            String key = (String)en.nextElement();
            String value = rb.getString(key);
            jowaProps.setProperty(key,value);
        }
        // merge with user properties bundle
        try {
          String userProps = jowaProps.getProperty("com.prism.toolkit.user.bundle","user");
          rb = ResourceBundle.getBundle(userProps);
          en = rb.getKeys();
          while(en.hasMoreElements()) {
            String key = (String)en.nextElement();
            String value = rb.getString(key);
            jowaProps.setProperty(key,value);
          }
        } catch (MissingResourceException mre) {
          // This is not a fatal error, user can't define user.properties bundled
          log.warn(".INITIALIZE()",mre);  
        }
        cgiVars = new Hashtable();
        JowaSec.SETAUTHORIZATION(JowaSec.NO_CHECK);
        Jxtf.encoding = Jxtf.defaultEncoding;
        Jxtf.contentType = Jxtf.defaultContentType;
        Jxtp.notInitialize = true;
        Jxtp.closeHeader = false;
        req = null;
        res = null;
        parsedCookies = null;
        log.debug(".INITIALIZE Jowa and logger successful.");
        return (majVersion * 256 + minVersion);
    }

    public static void parseCookies() {
        parsedCookies = new Hashtable();
        // Divide the string cookie format in fields by the ;
        try {
            String cookieStr = Jowa.GETCGIVAR("HTTP_COOKIE");
            if (cookieStr==null) // sanity checks
              return;
            StringTokenizer st =
                new StringTokenizer(cookieStr, ";");
            while (st.hasMoreElements()) {
                // the name = value pairs is required
                String s1 = (String)st.nextElement();
                String namestr = s1.substring(0, s1.indexOf("=")).trim();
                String valuestr = s1.substring(s1.indexOf("=") + 1);
                parsedCookies.put(namestr, valuestr);
                if (log.isDebugEnabled())
                  log.debug(".parseCookies - adding key='"+namestr+"' value='"+valuestr+"'");
            }
        } catch (Exception e) {
            // System.out.println should be in ORACLE_BASE/admin/instance/udump/*.trc files
            log.warn(".parseCookies - exception "+e.getMessage(),e);
        }
    }

    public static void FINALIZE() throws SQLException {
        // Clean-up request objects
        log.debug(".FINALIZE Jowa and logger called.");
        Jxtp.free();
        if (parsedCookies!=null)
          parsedCookies.clear();
        jowaProps.clear();
        jowaProps = null;
        parsedCookies = null;
        log = null;
        cgiVars = null;
        protectionRealm = null;
        userId = null;
        password = null;
        ipAddress = null;
        hostname = null;
        req = null;
        res = null;
    }

    public static void SETCGIVAR(String varName, String varValue) {
        cgiVars.put(varName, varValue);
    }

    public static void SETCGIVARS(byte[] varNames, byte[] varValues) throws SQLException {
        JowaArray names = new JowaArray(varNames);
        JowaArray values = new JowaArray(varValues);
        for (int i = 0; i < names.size; i++) {
            cgiVars.put(names.getValueAt(i), values.getValueAt(i));
        }
    }

    // only used in Java Stored Procedures
    public static String GETCGIVAR(String varName) {
        return (String)cgiVars.get(varName);
    }

    // only used in Java Stored Procedures
    public static Enumeration GETCGIVARS() {
        return cgiVars.keys();
    }

    // only used in Java Stored Procedures
    public static HttpServletResponse getHttpServletResponse() {
        if (res==null)
          res = new JxtpHttpServletResponse();
        return res;
    }

    // only used in Java Stored Procedures
    public static HttpServletRequest getHttpServletRequest() {
        if (req==null)
          req = new JxtpHttpServletRequest();
        return req;
    }

    // only used in Java Stored Procedures
     public static Properties getJowaProperties() {
         return jowaProps;
     }

    /**
     * @return String XML representation the HttpRequest for creating
     * XMLType instances.
     */
    public static String getJowaRequestAsString() {
         StringBuffer result = new StringBuffer("<?xml version=\"1.0\" encoding=\""+Jowa.GETCGIVAR("REQUEST_CHARSET")+"\"?>\n").
           append("<cgi xnlns=\"http://www.dbprism.com.ar/jowa/2.1/request.xsd\">\n");
         Enumeration cgiList = cgiVars.keys();
         while(cgiList.hasMoreElements()) {
           String key = (String)cgiList.nextElement();
           result.append("  <").append(key).append('>').append(Jxtp.replace2((String)cgiVars.get(key))).append("</").append(key).append(">\n");
         }
         Enumeration cookieList = parsedCookies.keys();
         result.append("\n  <cookies>");
         while(cookieList.hasMoreElements()) {
             String key = (String)cookieList.nextElement();
             String attrName;
             if ((key.charAt(0)>='a' && key.charAt(0)<='z') || (key.charAt(0)>='A' && key.charAt(0)<='Z') || key.charAt(0)=='_') 
               attrName = key;
             else // add extra underscore to be a valid tag name
               attrName = "_"+key;
             result.append("\n  <").append(attrName).append('>').append(Jxtp.replace2((String)parsedCookies.get(key))).append("</").append(attrName).append('>');
         }
         result.append("\n  </cookies>");
         result.append("\n</cgi>");
         return result.toString();
     }
}
